import { Products } from 'leaflet-fishmap';
import { getClosestDateTime } from '@/utils/data.js';
import VueStore from '@/store/index.js';
import { formatDisplayLatLng, formatDisplayData } from '@/utils/common.js';
import * as CONSTANTS from "@/config/constants.js";
import OceandataApi from '@/server/data/oceanData.js';

class LMap {
    constructor(divId, options) {
        this.initMap(divId, options);
        this.products = null;
        this.timeout = null;
    }

    initMap(divId, options) {
        this.map = L.map(divId, options);
    }
    getLMap() {
        return this.map;
    }
    initProducts({ isSyncMode, colorBar }) {
        this.products = new Products({ map: this.map, isSyncMode, colorBar });
    }
    getProducts() {
        return this.products;
    }
    getOceanData() {
        if (!this.map.pointsCache) { return []; }

        let oceanDataList = [];
        for (const key in this.map.pointsCache) {
            let pixelValue;
            if (this.map.pointsCache[key].dimension == 1) {
                pixelValue = this.map.pointsCache[key].u ? this.map.pointsCache[key].u.toFixed(3) : 0;
            } else {
                pixelValue = this.map.pointsCache[key].u && this.map.pointsCache[key].v ? Math.sqrt(Math.pow(this.map.pointsCache[key].u, 2) + Math.pow(this.map.pointsCache[key].v, 2)).toFixed(3) : 0;
            }
            oceanDataList.push({ name: key, value: pixelValue });
        }
        return oceanDataList;
    }
    getOceanDataByLatlng(latlng) {
        let layerList = this.products.getProductLayers();
        const products = this.getProducts();
        const oceanDataList = []
        layerList.forEach(layer => {
            let pixelValue = products.getLayerPixelValue(layer, latlng);
            if (!pixelValue) { return; }

            if (pixelValue.dimension == 1) {
                pixelValue = pixelValue.u ? pixelValue.u.toFixed(3) : 0;
            } else {
                pixelValue = pixelValue.u && pixelValue.v ? Math.sqrt(Math.pow(pixelValue.u, 2) + Math.pow(pixelValue.v, 2)).toFixed(3) : 0;
            }
            oceanDataList.push({ name: layer.options.name, value: pixelValue });
        })
        return oceanDataList;
    }
    async getOceanDepthDebounce(lat, lng) {
        if (this.timeout) {
            clearTimeout(this.timeout);
        }
        this.timeout = setTimeout(async () => {
            const result = await OceandataApi.getOceanDepth(lat, lng);
            if (result.isOk) {
                const value = result.data[0].elevation;
                const name = value >= 0 ? '高程' : '水深';
                const titleDom = document.getElementById('popup-terrain-title');
                const valueDom = document.getElementById('popup-terrain-value');
                if (titleDom) {
                    titleDom.innerHTML = name + ':';
                }
                if (valueDom) {
                    valueDom.innerHTML = `${value} m`;
                }
            }
        }, 100);
    }

    // 地图操作函数组
    setView(latlon, zoom) {
        this.map.setView(latlon, zoom);
    }
    getCenter() {
        return this.map.getCenter();
    }
    on(event, callback) {
        this.map.on(event, callback);
    }
    wrapLatLng(latlng) {
        return this.map.wrapLatLng(latlng);
    }

    // 图层操作函数组
    initLayers()     //初始化层
    {

        // 3. 添加底图层
        // 3.1 添加grayland
        let graylandURL = 'https://app.aispatial.com/grayland/{z}/{x}/{y}.png';
        let graylandLayer = L.tileLayer(graylandURL, {
            pane: 'landPane',
            updateWhenIdle: false
        });
        // graylandLayer.style.pointerEvents = 'none';
        graylandLayer.addTo(this.map);
        // 3.2 添加地名label，这里可以使用天地图进行替换
        var urlGoogle = 'https://wechat.globfishing.com/DataServer/?T=cta_w&tk=dca1488628f53bb67c13dc714d31046d&x={x}&y={y}&l={z}'
        let labelLayer = L.tileLayer(urlGoogle, {
            attribution: '<a href="https://www.openstreetmap.org/">天地图</a>',
            subdomains: 'bcd',
            pane: 'shadowPane',
            updateWhenIdle: false
        });
        // labelLayer.style.pointerEvents = 'none';
        labelLayer.addTo(this.map);
        // 3.3 添加海洋线阴影
        var coastlineURL = 'https://app.aispatial.com/coastline/{z}/{x}/{y}.png';
        let coastlineLayer = L.tileLayer(coastlineURL, {
            pane: 'shadowPane',
            updateWhenIdle: false
        });
        // coastlineLayer.style.pointerEvents = 'none';
        coastlineLayer.addTo(this.map);
    }
    addLayer(layer) {
        layer.addTo(this.map);
    }
    createOceanProductLayer(oceanFeature) {
        const date = new Date();
        const dateTime = getClosestDateTime(oceanFeature.name, date);
        const options = { ...dateTime };
        options.depth = 0;
        let oceanLayer = this.products.getProduct(oceanFeature.dataName, options);
        return oceanLayer;
    }
    createLayerGroup(markers) {
        return L.layerGroup(markers);
    }
    createBasanMarkerList(basanList) {
        const markerList = [];
        return markerList;
    }

    // 弹窗操作函数组
    async createOceanProductsPopup(e) {
        if (!e.latlng) { return; }

        const wrapLatlng = this.map.wrapLatLng(e.latlng);
        const oceanDataList = this.getOceanData(this.map);
        const list = VueStore.getters['oceanFeature/oceanFeatureList'];
        let featureList = [];
        if (this.products.isSyncMode) {
            featureList = list;
        } else {
            const scalarLayer = this.products.getScalarLayer();
            const particleLayer = this.products.getParticleLayer();
            const scalarFeature = list.find(item => item.displayName === scalarLayer.options.name);
            const particleFeature = list.find(item => item.displayName === particleLayer.options.name);
            featureList.push(scalarFeature)
            if (scalarFeature.name !== particleFeature.name) {
                featureList.push(particleFeature)
            }
        }
        const formattedlatlng = formatDisplayLatLng(wrapLatlng);
        let html =
            `<div class="popup-lat">${formattedlatlng.lat}</div>
          <div class="popup-lng">${formattedlatlng.lng}</div>
          <div class="popup-body">`;
        //获取当前显示的海况要素，放在最顶端

        let currentFeature = featureList.find(feature => feature.name === VueStore.state.oceanFeature.feature.name);

        const featureData = oceanDataList.find(oc => oc.name === currentFeature.displayName);
        let value = featureData ? featureData.value : 0;
        const popupData = formatDisplayData(currentFeature, value);
        html +=
            `<div class="popup-item-container">
          <span id="popup-${currentFeature.name}-title">${currentFeature.displayName}:</span>
          <span id="popup-${currentFeature.name}-value">${popupData.value} ${popupData.unit}</span>
        </div>`

        //获取其他海况要素
        featureList.forEach(feature => {
            if (feature.name == VueStore.state.oceanFeature.feature.name || feature.name == CONSTANTS.OceanFeatureEnum.SEA_CHART.name) { return; }

            const featureData = oceanDataList.find(oc => oc.name === feature.displayName);
            let value = featureData ? featureData.value : 0;
            const popupData = formatDisplayData(feature, value);
            html +=
                `<div class="popup-item-container popup-secondary-item">
            <span id="popup-${feature.name}-title">${feature.displayName}:</span>
            <span id="popup-${feature.name}-value">${popupData.value} ${popupData.unit}</span>
          </div>`
        });

        //水深做单独处理
        const result = await OceandataApi.getOceanDepth(wrapLatlng.lat, wrapLatlng.lng)
        if (result.isOk) {
            const value = result.data[0].elevation;
            const name = value >= 0 ? '高程' : '水深';
            html +=
                `<div class="popup-item-container popup-secondary-item">
            <span id="popup-terrain-title">${name}:</span>
            <span id="popup-terrain-value">${value} m</span>
          </div></div>`
        }
        const popup = L.popup({ autoPan: false, closeOnEscapeKey: false, closeOnClick: false }).setLatLng(e.latlng).setContent(html);
        popup.openOn(this.map);
        VueStore.commit('mapState/setPopupId', popup._leaflet_id);
    }

    async setPopupContent(e, popup) {
        if (!e.latlng) { return; }

        const wrapLatlng = this.map.wrapLatLng(e.latlng);
        const oceanDataList = this.products.isSyncMode ? this.getOceanData(this.map) : this.getOceanDataByLatlng(wrapLatlng);
        const list = VueStore.getters['oceanFeature/oceanFeatureList'];
        let featureList = [];
        if (this.products.isSyncMode) {
            featureList = list;
        } else {
            const scalarLayer = this.products.getScalarLayer();
            const particleLayer = this.products.getParticleLayer();
            const scalarFeature = list.find(item => item.displayName === scalarLayer.options.name);
            const particleFeature = list.find(item => item.displayName === particleLayer.options.name);
            featureList.push(scalarFeature)
            if (scalarFeature.name !== particleFeature.name) {
                featureList.push(particleFeature)
            }
        }
        const formattedlatlng = formatDisplayLatLng(wrapLatlng);
        const latDom = document.getElementsByClassName('popup-lat')[0];
        if (latDom) latDom.innerHTML = formattedlatlng.lat;
        const lngDom = document.getElementsByClassName('popup-lng')[0];
        if (lngDom) lngDom.innerHTML = formattedlatlng.lng;

        let html = '';
        let currentFeature = featureList.find(feature => feature.name === VueStore.state.oceanFeature.feature.name);
        const featureData = oceanDataList.find(oc => oc.name === currentFeature.displayName);
        let value = featureData ? featureData.value : 0;
        const popupData = formatDisplayData(currentFeature, value);

        html +=
            `<div class="popup-item-container">
          <span id="popup-${currentFeature.name}-title">${currentFeature.displayName}:</span>
          <span id="popup-${currentFeature.name}-value">${popupData.value} ${popupData.unit}</span>
        </div>`
        featureList.forEach(feature => {
            if (feature.name == VueStore.state.oceanFeature.feature.name || feature.name == CONSTANTS.OceanFeatureEnum.SEA_CHART.name) { return; }

            const featureData = oceanDataList.find(oc => oc.name === feature.displayName);
            let value = featureData ? featureData.value : 0;
            const popupData = formatDisplayData(feature, value);
            html +=
                `<div class="popup-item-container popup-secondary-item">
            <span id="popup-${feature.name}-title">${feature.displayName}:</span>
            <span id="popup-${feature.name}-value">${popupData.value} ${popupData.unit}</span>
          </div>`
        });
        html +=
            `<div class="popup-item-container popup-secondary-item">
            <span id="popup-terrain-title">水深:</span>
            <span id="popup-terrain-value">... m</span>
          </div>`
        const dom = document.getElementsByClassName('popup-body')[0];
        if (dom) {
            dom.innerHTML = html;
        }
        //水深做单独处理
        this.getOceanDepthDebounce(wrapLatlng.lat, wrapLatlng.lng);
        popup.setLatLng(e.latlng);
    }

    containerPointToLayerPoint(point) {
        return this.map.containerPointToLayerPoint(point)
    }
    latLngToContainerPoint(latlng) {
        return this.map.latLngToContainerPoint(latlng)
    }
    getContainer() {
        return this.map.getContainer();
    }
}

export default LMap;